#include "Containers/AxisNamed.h"
#include "Containers/TokenizedLine.h"
#include "TString.h"
#include <cmath>
#include <iostream>
#include <sstream>
using namespace std;

void AxisNamed::Import(const TString& input)
{
  TokenizedLine tokenizer{input};
  if(!input.Contains(","))
    NamedObject::SetName(input);
  else
    ImportNamingAndBinning(input);
}

void AxisNamed::Import(const YAML::Node& input)
{
  const auto& name = input["name"];
  if(!name)
  {
    cout << "ERROR: Cannot load this YAML value" << endl;
    return;
  }
  SetName(input);
  SetTitle(input);
  SetUnit(input);
  SetBinning(input);
}

void AxisNamed::SetUnit(const YAML::Node& input)
{
  const auto& unit = input["unit"];
  if(!unit) return;
  fUnit = unit.as<string>().c_str();
}

void AxisNamed::SetName(const YAML::Node& input)
{
  const auto& name = input["name"];
  if(!name) return;
  NamedObject::SetName(name.as<string>().c_str());
}

void AxisNamed::SetTitle(const YAML::Node& input)
{
  const auto& title = input["title"];
  if(!title) return;
  NamedObject::SetTitle(title.as<string>().c_str());
}

void AxisNamed::ImportNamingAndBinning(const TString& input)
{
  TokenizedLine tokenizer{input};
  const Int_t   firstBinningArg = tokenizer.GetNSegments() - 3;
  if(firstBinningArg < 1) return;
  ImportNaming(tokenizer.BuildMergedSegments(0, firstBinningArg - 1));
  SetBinning(tokenizer.BuildMergedSegments(firstBinningArg, -1));
}

void AxisNamed::ImportNaming(const TString& input)
{
  TokenizedLine tokenizer{input};
  switch(tokenizer.GetNSegments())
  {
    case 3: SetUnit(tokenizer.GetSegment(2));
    case 2: NamedObject::SetTitle(tokenizer.GetSegment(1));
    case 1: NamedObject::SetName(tokenizer.GetSegment(0));
  }
}

const TString AxisNamed::BuildAxisLabel() const
{
  if(!HasBinning()) return "";
  TString label{GetName()};
  if(HasTitle()) label = GetTitle();
  if(HasUnit()) label += Form(" (%s)", fUnit.Data());
  return label;
}

const TString AxisNamed::BuildCountLabel() const
{
  TString label{"counts"};
  if(!HasBinning()) return label;
  label += Form(" / %g", BinWidth());
  if(HasUnit()) label += Form(" %s", fUnit.Data());
  return label;
}

const TString AxisNamed::BuildString() const
{
  TString output{BuildString_Named()};
  if(HasUnit()) output += Form(" in %s", GetUnit());
  if(HasBinning()) output += Form(": %s", BuildString_AxisBinning().Data());
  return output;
}